﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LUC.Views;
using LUC.Domains;
using System.Drawing.Drawing2D;

namespace LUC
{
	
	public partial class MainView:Form
	{
		bool pressed;
		Point position;
		
		Point form_position;

		Feed cur_feed;
		
		UserSettings us;

		List<Label> lb_notifications, lb_deadlines;
		List<CheckBox> ch_titles;
		Label l_prompt = new Label();

		// On first run Width of ViewEvents = 200 (for example), and then will changed. 
		//If width will increased, form will be moved away from last loaded position, which are set user.
		// if already_open = false, this means what form must be represented in last saved position
		bool already_open = false;

		// allow hided ViewEvents, needed when pressed 'Esc' on UserSettings, and in this case
		// ViewEvents hided too, together UserEvents 
		public bool allow_hide;

		//indicator to launch RedrawCurLabels by tm_update. = true, if even one current labels 
		//has hours and minutes, and if launched MsCategoryChoice, else = false.
		bool need_update = false;
		
//------------------------------------------------------------------------------------------------		
		public MainView()
		{
			InitializeComponent();
			
			l_prompt.Parent = this;
            l_prompt.AutoSize = true;
			l_prompt.Font = new Font("Times New Roman", 20, FontStyle.Italic);
			l_prompt.MouseDown += new MouseEventHandler(MsDown);
            l_prompt.MouseMove += new MouseEventHandler(MsMove);
            l_prompt.MouseUp += new MouseEventHandler(MsUp);
            l_prompt.MouseDoubleClick+=new MouseEventHandler(MSDblClick);

			this.MouseDown += new MouseEventHandler(MsDown);
			this.MouseMove += new MouseEventHandler(MsMove);
			this.MouseUp += new MouseEventHandler(MsUp);
			this.MouseDoubleClick += new MouseEventHandler(MSDblClick);

			tm_launch.Enabled = true;
		}
		private void MainView_Load(object sender, EventArgs e)
		{
			try
			{
				cur_feed = DATA.feeds.First(x=>x.id_feed == Program.luc_set.last_id_feed);
			}
			catch
			{
				cur_feed = null;
			}
			BackColor = ColorTranslator.FromWin32(DATA.main_set.main_color);
			Redraw();
			
			if (Program.luc_set.pos_x < 0 || Program.luc_set.pos_y < 0)
			{
				Program.luc_set.pos_x = Screen.PrimaryScreen.WorkingArea.Width - Width;
				Program.luc_set.pos_y = Screen.PrimaryScreen.WorkingArea.Height - Height;
				Program.luc_set.Save();
			}
			SetPosition(Program.luc_set.pos_x, Program.luc_set.pos_y);
			Left = form_position.X;
			Top = form_position.Y;
		}

		void MsDown(object sender, MouseEventArgs e)
		{
			if (e.Button == MouseButtons.Right)
				ShowHide(null, null);
			else
			{
				pressed = true;
				position.X = e.X;
				position.Y = e.Y;
			}

		}
        void MsMove(object sender, MouseEventArgs e)
		{
			if (pressed)
				SetPosition(this.Left + e.X - position.X, this.Top + e.Y - position.Y);
		}
		void MsUp(object sender, MouseEventArgs e)
		{
			pressed = false;
			Program.luc_set.pos_x = form_position.X;
			Program.luc_set.pos_y = form_position.Y;
			Program.luc_set.Save();
		}
		void MSDblClick(object sender, MouseEventArgs e)
		{
			ViewSettings();
		}
		private void MainView_KeyDown(object sender, KeyEventArgs e)
		{
			switch (e.KeyCode)
			{
				case Keys.F12:
					ViewSettings();
					break;

				case Keys.Escape:
					if (!allow_hide)
					{
						allow_hide = true;
						return;
					}
					ShowHide(null, null);
					break;
			}
		}

		void MsCategoryChoice(object sender, MouseEventArgs e)
		{
			if (cur_feed == (Feed)((CheckBox)sender).Tag)
				return;
			cur_feed = (Feed)((CheckBox)sender).Tag;
			Program.luc_set.last_id_feed = cur_feed.id_feed;
			Program.luc_set.Save();
			Redraw();
		}
		void KeyDownChoice(object sender, KeyEventArgs e)
		{
			if ((e.KeyCode == Keys.Enter) || (e.KeyCode == Keys.Space))
				MsCategoryChoice(sender, null);
		}
		
		public void ShowHide(object sender, EventArgs e)
		{
			if (Program.luc_set.hidden)
			{
				Show();
				Focus();
				c_menu.Items["sm_hide"].Text = "Hide";
			}
			else
			{
				Hide();
				c_menu.Items["sm_hide"].Text = "Restore";
			}
			Program.luc_set.hidden = !Program.luc_set.hidden;
			Program.luc_set.Save();
		}
		private void SetPosition(int x, int y)
		{
			Rectangle r = Screen.PrimaryScreen.WorkingArea;
			if (y + this.Height + Program.luc_set.attach_distance > r.Bottom)
				this.Top = r.Bottom - this.Height;
			else
			{
				if (y - Program.luc_set.attach_distance < r.Top)
					this.Top = r.Top;
				else
					this.Top = y;
			}

			if (x + this.Width + Program.luc_set.attach_distance > r.Right)
				this.Left = r.Right - this.Width;
			else
			{
				if (x - Program.luc_set.attach_distance < r.Left)
					this.Left = r.Left;
				else
					this.Left = x;
			}
			form_position.X = Left;
			form_position.Y = Top;
		}
		public void ViewSettings()
		{
			try
			{
				us.Show();
				us.SetFeed(cur_feed);
			}
			catch
			{
				us = new UserSettings(this);
				us.Show();
				us.SetFeed(cur_feed);
			}
			if (us.WindowState == FormWindowState.Minimized)
				us.WindowState = FormWindowState.Normal;
			us.Focus();
		}
			
		public void Redraw()
		{
			SuspendLayout();
			
			#region delete checkboxes
			try
			{	for (int i = 0; i < ch_titles.Count; i++)
					ch_titles[i].Dispose();
				ch_titles.Clear();
			}
			catch
			{ }
			#endregion

			ResumeLayout(); // for correct Autowidth to checkboxes and labels
			#region draw checkboxes
			ch_titles = new List<CheckBox>();
			int num = 0;
			foreach (Feed feed in DATA.feeds)
			{
				CheckBox ch = new CheckBox
				{
					Name = "feed_ " + num.ToString(),
					Parent = this,
					AutoCheck = false,
					Tag = feed,
					Appearance = Appearance.Button,
					AutoSize = true,
					BackColor = this.BackColor,
					FlatStyle = FlatStyle.Flat,
					Text = feed.name,
					Font = feed.font_disp,
					Visible = false
				};
				
				ch.FlatAppearance.CheckedBackColor = feed.color_disp;
				ch.MouseDown += new MouseEventHandler(MsCategoryChoice);
				ch.KeyDown +=new KeyEventHandler(KeyDownChoice);

				ch_titles.Add(ch);
				num++;
			}
			#endregion

			int cur_lowest_coordinate = Top + Height;
			int cur_rightest_coordinate = Left + Width;

			int max_width_name = 0;
			int max_width_deadline = 0;
			#region if [ALL Empty]
			if (ch_titles.Count == 0)
			{
				l_prompt.Visible = true;
				l_prompt.Text = "Press F12 to open program settings";

				Width = l_prompt.Width + 2 * Program.luc_set.indent;
				Height = l_prompt.Height + 2 * Program.luc_set.indent;
				
				SetPosition(Left, cur_lowest_coordinate - Height);
				return;
			}
			else
				l_prompt.Visible = false;
			#endregion

			#region Mark BOLD and Checked selected category

			if (!ch_titles.Exists(x => ((Feed)x.Tag) == cur_feed))
			{
				cur_feed = (Feed)ch_titles[0].Tag;
				Program.luc_set.last_id_feed = cur_feed.id_feed;
			}
			foreach (CheckBox ch in ch_titles)
			{
				if (((Feed)ch.Tag).id_feed == cur_feed.id_feed)
				{
					ch.Font = new Font(ch.Font, FontStyle.Bold);
					ch.Checked = true;
					ch.FlatAppearance.BorderSize = 0;
				}
				else
				{
					ch.Font = new Font(ch.Font, FontStyle.Regular);
					ch.Checked = false;
					ch.FlatAppearance.BorderSize = 1;
				}
			}
			#endregion

			#region delete Labels
			try
			{
				for (int i = 0; i < lb_notifications.Count; i++)
				{
					lb_notifications[i].Dispose();
					lb_deadlines[i].Dispose();
				}
				lb_notifications.Clear();
				lb_deadlines.Clear();
			}
			catch
			{ }
			#endregion

			// Get cur_events from DataAccess
			int cur_top = Program.luc_set.indent;

			#region if [Empty curpos_category]
			if (cur_feed.notifications.Count == 0)
			{
				l_prompt.Visible = true;
				l_prompt.Text = "Категория/Рассылка пуста!";
				cur_top += l_prompt.Height + Program.luc_set.control_distance;
				max_width_name = l_prompt.Width;
				max_width_deadline = 0;
			}
			#endregion

			lb_notifications = new List<Label>(cur_feed.notifications.Count);
			lb_deadlines = new List<Label>(cur_feed.notifications.Count);

			need_update = false;
			num = 0;
			foreach (Notification n in cur_feed.notifications)
			{
				Label l_name = new Label
				{
					Name = Program.luc_set.start_name_agreement + "name_" + num.ToString(),
					Tag = n,
					Parent = this,
					Visible = true,
					AutoSize = true,
					Font = n.font_disp,
					ForeColor = n.color_disp,
					BackColor = this.BackColor,
					Text = n.text + ":",
					Left = Program.luc_set.indent,
					Top = cur_top
				};

				l_name.MouseDown += new MouseEventHandler(MsDown);
				l_name.MouseMove += new MouseEventHandler(MsMove);
				l_name.MouseUp += new MouseEventHandler(MsUp);
				l_name.MouseDoubleClick += new MouseEventHandler(MSDblClick);

				lb_notifications.Add(l_name);

				// ---

				Label l_deadline = new Label
				{
					Name = Program.luc_set.start_name_agreement + "deadline_" + num.ToString(),
					Tag = n,
					Parent = this,
					Visible = true,
					AutoSize = true,
					Font = n.font_disp,
					ForeColor = n.color_disp,
					BackColor = this.BackColor,
					Text = Controller.GetText(n.deadline, ref need_update),
					Top = cur_top
				};

				l_deadline.MouseDown += new MouseEventHandler(MsDown);
				l_deadline.MouseMove += new MouseEventHandler(MsMove);
				l_deadline.MouseUp += new MouseEventHandler(MsUp);
				l_deadline.MouseDoubleClick += new MouseEventHandler(MSDblClick);

				lb_deadlines.Add(l_deadline);

				cur_top += l_name.Height + Program.luc_set.control_distance;
				num++;
			}
			SuspendLayout();

			if (lb_notifications.Count > 0)
			{
				max_width_name = lb_notifications.Max(x => x.Width);
				max_width_deadline = lb_deadlines.Max(x => x.Width);
			}

			//Counting SUM(Width categories buttons) and SET WIDTH
			int ch_all_width = ch_titles.Sum(x => x.Width) + ch_titles.Count * Program.luc_set.indent;
			Width = Math.Max((max_width_name + max_width_deadline), ch_all_width);
			Height = cur_top + ch_titles.Max(x => x.Height);
			
			// Set categories button's left positions
			int cur_left = Width;
			for (int i = ch_titles.Count - 1; i >= 0; i--)
			{
				ch_titles[i].Top = cur_top;
				cur_left -= (ch_titles[i].Width + Program.luc_set.control_distance);
				ch_titles[i].Left = cur_left;
				ch_titles[i].Visible = true;
			}
			//Set deadline label's  left positions
			for (int i = 0; i < lb_deadlines.Count; i++)
				lb_deadlines[i].Left = max_width_name + Program.luc_set.indent;

			pressed = false;
			if (!already_open)
			{
				already_open = true;
				cur_rightest_coordinate = Left + Width;
				cur_lowest_coordinate = Top + Height;
			}
			SetPosition(cur_rightest_coordinate - Width, cur_lowest_coordinate - Height);
			
			Update();
			ResumeLayout();	
		}
		//public GraphicsPath DrawRoundedRectangle()
// 		{
// 			GraphicsPath gp = new GraphicsPath();
// 			
// 			float radius = 2;
// 			
// 			float left = (float)Left;
// 			float top = (float)Top;
// 			float height = (float)Height;
// 			float width = (float)Width;
// 
// 			gp.AddLine(left + radius, top, left + width - (radius * 2), top);
// 			gp.AddArc(left + width - (radius * 2), top, radius * 2, radius * 2, 270, 90);
// 			gp.AddLine(left + width, top + radius, left + width, top + height - (radius * 2));
// 			gp.AddArc(left + width - (radius * 2), top + height - (radius * 2), radius * 2, radius * 2, 0, 90);
// 			gp.AddLine(left + width - (radius * 2), top + height, left + radius, top + height);
// 			gp.AddArc(left, top + height - (radius * 2), radius * 2, radius * 2, 90, 90);
// 			gp.AddLine(left, top + height - (radius * 2), left, top + radius);
// 			gp.AddArc(left, top, radius * 2, radius * 2, 180, 90);
// 			gp.CloseFigure();
// 			return gp;
// 		}

		private void parametersToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ViewSettings();
		}
		private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
		{
			MessageBox.Show("Let Us Count: Joint project by developers:\nAlexander Bezdenezhnyh, "+
			"aka zxsanny, ICQ 448856043\nIaroslav Sergeev, aka noomorph, ICQ 394067955", "About LUC",
			MessageBoxButtons.OK, MessageBoxIcon.Information);

		}
		private void exitToolStripMenuItem_Click(object sender, EventArgs e)
		{
			Close();
		}

		private void showToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ShowHide(null, null);
		}

		private void n_icon_MouseClick(object sender, MouseEventArgs e)
		{
			if (e.Button != MouseButtons.Right)
				ShowHide(null, null);
		}

		void CheckChanges()
		{
			bool need_redraw = false;
			foreach (Feed feed in DATA.feeds)
			{
				foreach (Notification n in feed.notifications)
				{
					
				if (n.deadline <= DateTime.Now)
					{
						//PERIOD
						if ((n.increment_days!= 0) || (n.increment_hhmmss.TimeOfDay.Ticks > 0))
						{
							TimeSpan ts = new TimeSpan(
								n.increment_days,
								n.increment_hhmmss.Hour,
								n.increment_hhmmss.Minute,
								n.increment_hhmmss.Second);
							n.deadline = n.deadline.Add(ts);
							need_redraw = true;
						}
						
						//RING
						if (n.ringed)
						{
							if ((n.increment_days == 0) && (n.increment_hhmmss.TimeOfDay.Ticks== 0))
								n.ringed = false;
							new AttentionNotify(cur_feed.name + ":" + n.text, n).ShowDialog();
						}						
						
						//DELETE
						if (n.delete_happen)
						{
							feed.notifications.Remove(n);
							need_redraw = true;
						}
					}
				}
				if (need_redraw)
					Redraw();
			}
		}
		
		private void tm_launch_Tick(object sender, EventArgs e)
		{
			if (DateTime.Now.Second == 0)
			{
				tm_launch.Enabled = false;
				tm_update_Tick(null, null);
				
				tm_update.Enabled = true;
				tm_alarm.Enabled = true;
			}
		}
		private void tm_update_Tick(object sender, EventArgs e)
		{
			Redraw();
		}
		private void tm_alarm_Tick(object sender, EventArgs e)
		{
			CheckChanges();
		}
	}
}
